package org.xiaohaoniu.controller;

import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacv.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import org.xiaohaoniu.RtmpPushStream;

import java.io.InputStream;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@RestController
@CrossOrigin(origins = "*") // 允许所有跨域请求
public class WSController {

    private static final ConcurrentHashMap<String, StreamSession> activeSessions = new ConcurrentHashMap<>();
    private static final ExecutorService executor = Executors.newCachedThreadPool();

    @GetMapping("/start-stream")
    public SseEmitter startStream(@RequestParam(name = "streamKey") String streamKey) {
        SseEmitter emitter = new SseEmitter(0L); // 无超时限制
        executor.execute(() -> {
            try {
                StreamSession session = new StreamSession(streamKey, emitter);
                activeSessions.put(streamKey, session);
                session.start();
            } catch (Exception e) {
                emitter.completeWithError(e);
            }
        });
        return emitter;
    }

    @GetMapping("/stop-stream")
    public String stopStream(@RequestParam(name = "streamKey") String streamKey) {
        StreamSession session = activeSessions.get(streamKey);
        if (session != null) {
            session.stop();
            activeSessions.remove(streamKey);
            return "Stream stopped successfully";
        }
        return "Stream not found";
    }

    private static class StreamSession {
        private final String streamKey;
        private final SseEmitter emitter;
        private FFmpegFrameGrabber grabber;
        private FFmpegFrameRecorder recorder;
        private volatile boolean running = false;

        public StreamSession(String streamKey, SseEmitter emitter) {
            this.streamKey = streamKey;
            this.emitter = emitter;
        }

        public void start() throws Exception {
            running = true;

            Properties props = new Properties();
            InputStream input = RtmpPushStream.class.getClassLoader()
                    .getResourceAsStream("application.properties");
            if (input == null) {
                System.err.println("找不到 application.properties 文件");
                return;
            }
            props.load(input); // 加载 properties 文件



            String rtmpUrl = props.getProperty("rtmpUrl")+streamKey;

            String cameraDevice = props.getProperty("cameraDevice");
            String format = "dshow";

            String osName = System.getProperty("os.name").toLowerCase();
            if (osName.contains("linux")) {
                cameraDevice = props.getProperty("cameraDeviceLinux");
                format = "video4linux2";
            }

            grabber = new FFmpegFrameGrabber(cameraDevice);
            grabber.setFormat(format);
            grabber.setImageWidth(640);
            grabber.setImageHeight(480);
            grabber.start();

            recorder = new FFmpegFrameRecorder(rtmpUrl, 640, 480);
            recorder.setFormat("flv");
            recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
            recorder.setFrameRate(25);
            recorder.setGopSize(50);
            recorder.setVideoBitrate(800_000);
            recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
            recorder.setVideoOption("preset", "ultrafast");
            recorder.setVideoOption("tune", "zerolatency");
            recorder.start();

            emitter.send(SseEmitter.event().name("status").data("Stream started"));

            Frame frame;
            while (running && (frame = grabber.grab()) != null) {
                recorder.record(frame);
            }

            cleanup();
            emitter.send(SseEmitter.event().name("status").data("Stream ended"));
            emitter.complete();
        }

        public void stop() {
            running = false;
        }

        private void cleanup() {
            try {
                if (recorder != null) {
                    recorder.stop();
                    recorder.release();
                }
                if (grabber != null) {
                    grabber.stop();
                    grabber.release();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}